package com.nanyang.tms.manager.product.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.nanyang.common.core.annotation.SystemLog;
import com.nanyang.common.core.dict.CommonEnum;
import com.nanyang.common.core.page.PageBean;
import com.nanyang.common.core.page.PageTableBean;
import com.nanyang.common.tool.utils.uuid.GlobalIdGeneratorUtil;
import com.nanyang.tms.common.contstant.TmsSerializeConstant;
import com.nanyang.tms.common.dict.TmsCommonEnum;
import com.nanyang.tms.common.dict.TmsExceptionEnum;
import com.nanyang.tms.common.exception.TmsManagerException;
import com.nanyang.tms.common.util.TmsExceptionUtil;
import com.nanyang.tms.dao.product.*;
import com.nanyang.tms.domain.product.*;
import com.nanyang.tms.manager.product.ProductManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Slf4j
@Component("productManager")
public class ProductManagerImpl implements ProductManager {

    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private ProductRuleDao productRuleDao;
    @Autowired
    private ProductWeightModelDao productWeightModelDao;
    @Autowired
    private ProductWeightRuleDao productWeightRuleDao;
    @Autowired
    private ProductCarryRuleDao productCarryRuleDao;
    @Autowired
    private ProductPartDao productPartDao;
    @Autowired
    private GlobalIdGeneratorUtil globalIdGeneratorUtil;

    @Override
    public PageBean<ProductInfoVO> listProduct(ProductQuery query) {
        try {
            if (query == null) {
                log.error(TmsCommonEnum.PARAM_IS_NULL.getCode() + TmsCommonEnum.PARAM_IS_NULL.getMessage());
                throw new TmsManagerException(TmsCommonEnum.PARAM_IS_NULL.getCode() ,TmsCommonEnum.PARAM_IS_NULL.getMessage());
            }
            Integer count = productInfoDao.countProduct(query);
            PageBean<ProductInfoVO> page = new PageTableBean<ProductInfoVO>(query.getPageIndex(), query.getPageSize());
            if (null != count && count != 0) {
                page.setTotalItem(count);
                int startRow = page.getStartRow();
                if (startRow > 0) {
                    startRow -= 1;
                }
                query.setStartRow(startRow);
                page.addAll(productInfoDao.listProduct(query));
            }
            return page;
        } catch (Exception e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
    @SystemLog(module =SystemLog.Module.PRODUCT,template="productAdd")
    @Override
    @Transactional
    public void saveProduct(ProductBaseDO productBaseDO) {
        try{
            ProductInfoDO productInfoDO = productBaseDO.getProductInfoDO();
            ProductQuery query=new ProductQuery();
            query.setProductName(productInfoDO.getProductName());
            if (productInfoDao.queryVerifyProductName(query)>0){
               throw new TmsManagerException(TmsExceptionEnum.PRODUCT_IS_EXIST.getCode(),TmsExceptionEnum.PRODUCT_IS_EXIST.getMessage());
            };
            /*******产品基本信息***********/
            String productCode=TmsSerializeConstant.PRODUCT_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
            productInfoDO.setProductCode(productCode);
            productInfoDO.setGmtCreatePin(productBaseDO.getGmtCreatePin());
            productInfoDO.setIp(productBaseDO.getIp());
            productInfoDao.insert(productInfoDO);
            /*******产品规则信息***********/
            ProductRuleDO productRuleDO = productBaseDO.getProductRuleDO();
            String ruleCode=TmsSerializeConstant.PRODUCT_RULE_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_RULE_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
            productRuleDO.setRuleCode(ruleCode);
            productRuleDO.setProductCode(productCode);
            productRuleDO.setGmtCreatePin(productBaseDO.getGmtCreatePin());
            productRuleDO.setIp(productBaseDO.getIp());
            productRuleDao.insert(productRuleDO);
            /*******产品分区信息信息***********/
            List<ProductPartDO> productPartDOList = productBaseDO.getProductPartDOList();
            productPartDOList.forEach(productPartDO ->{
                String partCode=TmsSerializeConstant.PRODUCT_PART_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_PART_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
                productPartDO.setProductCode(productCode);
                productPartDO.setPartCode(partCode);
                productPartDO.setGmtCreatePin(productBaseDO.getGmtCreatePin());
                productPartDO.setIp(productBaseDO.getIp());
                productPartDao.insert(productPartDO);
            });
            /*******产品进位规则信息***********/
            List<ProductCarryRuleDO> productCarryRuleDOList = productBaseDO.getProductCarryRuleDOList();
            productCarryRuleDOList.forEach(productCarryRuleDO ->{
                String carryRuleCode=TmsSerializeConstant.PRODUCT_CARRY_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_CARRY_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
                productCarryRuleDO.setProductCode(productCode);
                productCarryRuleDO.setCarryRuleCode(carryRuleCode);
                productCarryRuleDO.setGmtCreatePin(productBaseDO.getGmtCreatePin());
                productCarryRuleDO.setIp(productBaseDO.getIp());
                productCarryRuleDao.insert(productCarryRuleDO);
            });
            /*******产品计重模式信息***********/
            ProductWeightModelDO productWeightModelDO = productBaseDO.getProductWeightModelDO();
            String weightModelCode=TmsSerializeConstant.PRODUCT_WEIGHT_MODEL_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_WEIGHT_MODEL_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
            productWeightModelDO.setProductCode(productCode);
            productWeightModelDO.setWeightModelCode(weightModelCode);
            productWeightModelDO.setGmtCreatePin(productBaseDO.getGmtCreatePin());
            productWeightModelDO.setIp(productBaseDO.getIp());
            productWeightModelDao.insert(productWeightModelDO);
            /*******产品计重模式规则信息***********/
            List<ProductWeightRuleDO> productWeightRuleDOList = productWeightModelDO.getProductWeightRuleDOList();
            productWeightRuleDOList.forEach(productWeightRuleDO ->{
                String weightRuleCode=TmsSerializeConstant.PRODUCT_WEIGHT_RULE_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_WEIGHT_RULE_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
                productWeightRuleDO.setWeightRuleCode(weightRuleCode);
                productWeightRuleDO.setWeightModelCode(weightModelCode);
                productWeightRuleDO.setGmtCreatePin(productBaseDO.getGmtCreatePin());
                productWeightRuleDO.setIp(productBaseDO.getIp());
                productWeightRuleDO.setConditionExpression(HtmlUtils.htmlUnescape(productWeightRuleDO.getConditionExpression()));
                productWeightRuleDao.insert(productWeightRuleDO);
            });
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
    @SystemLog(module =SystemLog.Module.PRODUCT,template="productUpdate")
    @Override
    @Transactional
    public  void updateProduct(ProductBaseDO productBaseDO){
        try {
            ProductInfoDO productInfoDO = productBaseDO.getProductInfoDO();
            ProductQuery query=new ProductQuery();
            query.setProductName(productInfoDO.getProductName());
            query.setProductCode(productInfoDO.getProductCode());
            if (productInfoDao.queryVerifyProductName(query)>0){
                throw new TmsManagerException(TmsExceptionEnum.PRODUCT_IS_EXIST.getCode(),TmsExceptionEnum.PRODUCT_IS_EXIST.getMessage());
            };
            Date date = new Date();
            productInfoDO.setGmtModified(date);
            productInfoDO.setGmtModifiedPin(productBaseDO.getGmtModifiedPin());
            productInfoDao.update(productInfoDO);

            ProductRuleDO productRuleDO = productBaseDO.getProductRuleDO();
            productRuleDO.setGmtModified(date);
            productRuleDO.setGmtModifiedPin(productBaseDO.getGmtModifiedPin());
            productRuleDao.update(productRuleDO);

            String productCode=productInfoDO.getProductCode();
            List<ProductCarryRuleVO> productCarryRuleVOS = productCarryRuleDao.selectByProductCode(productCode);
            List<ProductCarryRuleDO> productCarryRuleDOList = productBaseDO.getProductCarryRuleDOList();
            productCarryRuleVOS.forEach(productCarryRuleVO ->{
                Optional<ProductCarryRuleDO> productCarryRuleOptional = productCarryRuleDOList.stream().filter(item -> productCarryRuleVO.getCarryRuleCode().equals(item.getCarryRuleCode())).findFirst();
                if(!productCarryRuleOptional.isPresent()){//删除不存在的
                    productCarryRuleDao.deleteByPrimaryKey(productCarryRuleVO.getId());
                }
            });
            productCarryRuleDOList.forEach(productCarryRuleDO ->{
                if(Objects.isNull(productCarryRuleDO.getCarryRuleCode())){//编码不存在添加
                    String carryRuleCode=TmsSerializeConstant.PRODUCT_CARRY_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_CARRY_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
                    productCarryRuleDO.setProductCode(productCode);
                    productCarryRuleDO.setCarryRuleCode(carryRuleCode);
                    productCarryRuleDO.setGmtCreatePin(productBaseDO.getGmtModifiedPin());
                    productCarryRuleDO.setIp(productBaseDO.getIp());
                    productCarryRuleDao.insert(productCarryRuleDO);
                }else{//修改
                    productCarryRuleDO.setGmtModified(date);
                    productCarryRuleDO.setGmtModifiedPin(productBaseDO.getGmtModifiedPin());
                    productCarryRuleDao.update(productCarryRuleDO);
                }
            });

            List<ProductPartVO> productPartVOS = productPartDao.selectByProductCode(productCode);
            List<ProductPartDO> productPartDOList = productBaseDO.getProductPartDOList();
            productPartVOS.forEach(productPartVO ->{
                Optional<ProductPartDO> first = productPartDOList.stream().filter(item -> productPartVO.getPartCode().equals(item.getPartCode())).findFirst();
                if(!first.isPresent()){//删除不存在的
                    productPartDao.deleteByPrimaryKey(productPartVO.getId());
                }
            });
            productPartDOList.forEach(productPartDO ->{
                if(Objects.isNull(productPartDO.getPartCode())){//编码不存在添加
                    String partCode=TmsSerializeConstant.PRODUCT_PART_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_PART_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
                    productPartDO.setProductCode(productCode);
                    productPartDO.setPartCode(partCode);
                    productPartDO.setGmtCreatePin(productBaseDO.getGmtModifiedPin());
                    productPartDO.setIp(productBaseDO.getIp());
                    productPartDao.insert(productPartDO);
                }else{//修改
                    productPartDO.setGmtModified(date);
                    productPartDO.setGmtModifiedPin(productBaseDO.getGmtModifiedPin());
                    productPartDao.update(productPartDO);
                }
            });

            ProductWeightModelDO productWeightModelDO = productBaseDO.getProductWeightModelDO();
            productWeightModelDO.setGmtModified(date);
            productWeightModelDO.setGmtModifiedPin(productBaseDO.getGmtModifiedPin());
            productWeightModelDao.update(productWeightModelDO);
            List<ProductWeightRuleVO> productWeightRuleVOS = productWeightRuleDao.selectByModelCode(productWeightModelDO.getWeightModelCode());
            List<ProductWeightRuleDO> productWeightRuleDOList = productWeightModelDO.getProductWeightRuleDOList();
            productWeightRuleVOS.forEach(productWeightRuleVO ->{
                Optional<ProductWeightRuleDO> first = productWeightRuleDOList.stream().filter(item -> productWeightRuleVO.getWeightRuleCode().equals(item.getWeightRuleCode())).findFirst();
                if(!first.isPresent()){//删除不存在的
                    productWeightRuleDao.deleteByPrimaryKey(productWeightRuleVO.getId());
                }
            });
            productWeightRuleDOList.forEach(productWeightRuleDO ->{
                if(Objects.isNull(productWeightRuleDO.getWeightRuleCode())){//编码不存在添加
                    String weightRuleCode=TmsSerializeConstant.PRODUCT_WEIGHT_RULE_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.PRODUCT_WEIGHT_RULE_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY);
                    productWeightRuleDO.setWeightRuleCode(weightRuleCode);
                    productWeightRuleDO.setWeightModelCode(productWeightModelDO.getWeightModelCode());
                    productWeightRuleDO.setGmtCreatePin(productBaseDO.getGmtModifiedPin());
                    productWeightRuleDO.setIp(productBaseDO.getIp());
                    productWeightRuleDO.setConditionExpression(HtmlUtils.htmlUnescape(productWeightRuleDO.getConditionExpression()));
                    productWeightRuleDao.insert(productWeightRuleDO);
                }else{//修改
                    productWeightRuleDO.setGmtModified(date);
                    productWeightRuleDO.setGmtModifiedPin(productBaseDO.getGmtModifiedPin());
                    productWeightRuleDO.setConditionExpression(HtmlUtils.htmlUnescape(productWeightRuleDO.getConditionExpression()));
                    productWeightRuleDao.update(productWeightRuleDO);
                }
            });
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }


    };
    @Override
    public ProductBaseVO selectProductByCode(String productCode){
        try {
            ProductBaseVO productBaseVO=new ProductBaseVO();
            ProductInfoVO productInfoVO = productInfoDao.selectByCode(productCode);
            if(Objects.isNull(productInfoVO)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }

            productBaseVO.setProductInfoVO(productInfoVO);

            ProductRuleVO productRuleVO = productRuleDao.selectByProductCode(productCode);
            if(Objects.isNull(productRuleVO)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }
            productBaseVO.setProductRuleVO(productRuleVO);

            List<ProductCarryRuleVO> productCarryRuleVOS = productCarryRuleDao.selectByProductCode(productCode);
            if(CollectionUtil.isEmpty(productCarryRuleVOS)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }
            productBaseVO.setProductCarryRuleVOList(productCarryRuleVOS);

            List<ProductPartVO> productPartVOS = productPartDao.selectByProductCode(productCode);
            if(CollectionUtil.isEmpty(productPartVOS)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }
            productBaseVO.setProductPartVOList(productPartVOS);

            ProductWeightModelVO productWeightModelVO = productWeightModelDao.selectByProductCode(productCode);
            if(Objects.isNull(productWeightModelVO)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }

            List<ProductWeightRuleVO> productWeightRuleVOS = productWeightRuleDao.selectByModelCode(productWeightModelVO.getWeightModelCode());
            if(CollectionUtil.isEmpty(productWeightRuleVOS)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }
            productWeightModelVO.setProductWeightRuleVOList(productWeightRuleVOS);

            productBaseVO.setProductWeightModelVO(productWeightModelVO);

            return productBaseVO;
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
}
